﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Asko.Lib.Algorithms
{
    public abstract class AlgortihmBase
    {
        #region Champs
        private volatile object _syncRoot = new object();
        private Algorithm_State _state = Algorithm_State.NotRunning;
        #endregion

        #region Evénements
        public event EventHandler Finished;
        public event EventHandler Started;
        public event EventHandler StateChanged;
        #endregion

        #region Méthodes
        protected void BeginComputation()
        {
            lock (_syncRoot)
            {
                if (_state != Algorithm_State.NotRunning)
                {

                }
                _state = Algorithm_State.Running;
                OnStarted(EventArgs.Empty);

            }
        }
        public void Compute()
        {
            BeginComputation();
            InternalCompute();
            EndComputation();
        }
        protected void EndComputation()
        {
            lock (_syncRoot)
            {
                switch (_state)
                {
                    case Algorithm_State.Running:
                        _state = Algorithm_State.Finished;
                        OnFinished(EventArgs.Empty);
                        break;
                    default:
                        throw new InvalidOperationException();
                }
                OnStateChanged(EventArgs.Empty);
            }
        }
        protected abstract void InternalCompute();
        protected virtual void OnFinished(EventArgs e)
        {
            EventHandler eh = Finished;
            if (eh != null)
                eh(this, e);
        }
        protected virtual void OnStarted(EventArgs e)
        {
            EventHandler eh = Started;
            if (eh != null)
                eh(this, e);
        }
        protected virtual void OnStateChanged(EventArgs e)
        {
            EventHandler eh = StateChanged;
            if (eh != null)
                eh(this, e);
        }
        #endregion

        #region Propriétés
        /// <summary>
        /// Retourne l'état
        /// </summary>
        public Algorithm_State State
        {
            get
            {
                lock (_syncRoot)
                {
                    return _state;
                }

            }

        }
        public Object SyncRoot
        {
            get { return _syncRoot; }
        }
        #endregion
    }
    #region Types Imbriqués
    public enum Algorithm_State : int
    {
        Finished = 2,
        Running = 1,
        NotRunning = -1
    }
    #endregion
}
